package co.yixiang.yshop.module.crm.service.crmclues;

import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.ShopCommonEnum;
import co.yixiang.yshop.framework.common.exception.ErrorCode;
import co.yixiang.yshop.framework.mybatis.core.query.LambdaQueryWrapperX;
import co.yixiang.yshop.framework.security.core.util.SecurityFrameworkUtils;
import co.yixiang.yshop.module.crm.controller.admin.crmcustomer.vo.CrmCustomerImportVO;
import co.yixiang.yshop.module.crm.controller.admin.crmcustomer.vo.CrmCustomerSaveReqVO;
import co.yixiang.yshop.module.crm.controller.admin.crmcustomer.vo.CrmCustomerTransferVO;
import co.yixiang.yshop.module.crm.controller.admin.crmcustomer.vo.CustomerImportRespVO;
import co.yixiang.yshop.module.crm.dal.dataobject.crmcustomer.CrmCustomerDO;
import co.yixiang.yshop.module.crm.dal.dataobject.crmcustomercontacts.CrmCustomerContactsDO;
import co.yixiang.yshop.module.crm.dal.dataobject.crmrecord.CrmRecordDO;
import co.yixiang.yshop.module.crm.dal.mysql.crmcustomer.CrmCustomerMapper;
import co.yixiang.yshop.module.crm.dal.mysql.crmrecord.CrmRecordMapper;
import co.yixiang.yshop.module.crm.enums.CluesStatusEnum;
import co.yixiang.yshop.module.crm.enums.CustomerTypesEnum;
import co.yixiang.yshop.module.crm.enums.RelationEnum;
import co.yixiang.yshop.module.crm.enums.TypesEnum;
import co.yixiang.yshop.module.crm.service.crmoperatelog.CrmOperatelogService;
import co.yixiang.yshop.module.system.api.user.AdminUserApi;
import co.yixiang.yshop.module.system.dal.dataobject.user.AdminUserDO;
import co.yixiang.yshop.module.system.dal.mysql.user.AdminUserMapper;
import co.yixiang.yshop.module.system.service.user.AdminUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import co.yixiang.yshop.module.crm.controller.admin.crmclues.vo.*;
import co.yixiang.yshop.module.crm.dal.dataobject.crmclues.CrmCluesDO;
import co.yixiang.yshop.framework.common.pojo.PageResult;
import co.yixiang.yshop.framework.common.pojo.PageParam;
import co.yixiang.yshop.framework.common.util.object.BeanUtils;

import co.yixiang.yshop.module.crm.dal.mysql.crmclues.CrmCluesMapper;

import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.module.crm.enums.ErrorCodeConstants.*;

/**
 * 线索 Service 实现类
 *
 * @author yshop
 */
@Service
@Validated
public class CrmCluesServiceImpl implements CrmCluesService {

    @Resource
    private CrmCluesMapper cluesMapper;
    @Resource
    private AdminUserApi adminUserApi;
    @Resource
    private CrmCustomerMapper customerMapper;
    @Resource
    private CrmRecordMapper crmRecordMapper;
    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private AdminUserService adminUserService;
    @Resource
    private CrmOperatelogService crmOperatelogService;

    @Override
    public Long createClues(CrmCluesSaveReqVO createReqVO) {
        // 插入
        CrmCluesDO clues = BeanUtils.toBean(createReqVO, CrmCluesDO.class);
        clues.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId());
        cluesMapper.insert(clues);
        // 返回
        return clues.getId();
    }

    @Override
    public void updateClues(CrmCluesSaveReqVO updateReqVO) {
        // 校验存在
        validateCluesExists(updateReqVO.getId());
        // 更新
        CrmCluesDO updateObj = BeanUtils.toBean(updateReqVO, CrmCluesDO.class);
        cluesMapper.updateById(updateObj);
    }

    @Override
    public void deleteClues(Long id) {
        // 校验存在
        validateCluesExists(id);
        // 删除
        cluesMapper.deleteById(id);

        //删除记录
        crmRecordMapper.delete(new LambdaQueryWrapper<CrmRecordDO>()
                .eq(CrmRecordDO::getTypes, TypesEnum.CLUES.getValue())
                .eq(CrmRecordDO::getTypesId,id));
    }

    private void validateCluesExists(Long id) {
        if (cluesMapper.selectById(id) == null) {
            throw exception(CLUES_NOT_EXISTS);
        }
    }

    @Override
    public CrmCluesDO getClues(Long id) {
        return cluesMapper.selectById(id);
    }

    @Override
    public PageResult<CrmCluesRespVO> getCluesPage(CrmCluesPageReqVO pageReqVO) {
        if(CustomerTypesEnum.OPEN.getValue().equals(pageReqVO.getType())){
            return cluesMapper.selectPage2(pageReqVO);
        }
        List<Long> ids = new ArrayList<>();
        Long adminId = SecurityFrameworkUtils.getLoginUserId();
        if(RelationEnum.MY.getValue().equals(pageReqVO.getRelation())){
            ids.add(adminId);
        }else if(RelationEnum.SUB.getValue().equals(pageReqVO.getRelation())){
            ids = adminUserApi.getUserListBySubordinateIds(adminId);
        }
        return cluesMapper.selectPage(pageReqVO,ids);
    }

    @Override
    public void openClues(Long id) {
        CrmCluesDO crmCluesDO = cluesMapper.selectById(id);
        if(CluesStatusEnum.STATUS_0.getValue().equals(crmCluesDO.getStatus())){
            crmCluesDO.setStatus(CluesStatusEnum.STATUS_NEG_1.getValue());
        }
        crmCluesDO.setOwnerUserId(0L);
        cluesMapper.updateById(crmCluesDO);
    }

    @Override
    public void receiveClues(Long id) {
        CrmCluesDO crmCluesDO = cluesMapper.selectById(id);
        if (crmCluesDO == null) {
            throw exception(CLUES_NOT_EXISTS);
        }
        crmCluesDO.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId());
        crmCluesDO.setCollectTime(LocalDateTime.now());
        crmCluesDO.setFollowTime(LocalDateTime.now());
        cluesMapper.updateById(crmCluesDO);

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createCustomer(CrmCustomerSaveReqVO createReqVO) {
        CrmCluesDO crmCluesDO = cluesMapper.selectById(createReqVO.getId());
        if (crmCluesDO == null) {
            throw exception(CLUES_NOT_EXISTS);
        }
        if(CluesStatusEnum.STATUS_1.getValue().equals(crmCluesDO.getStatus())){
            throw exception(new ErrorCode(202411160,"已经转化成客户！"));
        }
        createReqVO.setId(null);
        CrmCustomerDO customerDO = BeanUtils.toBean(createReqVO,CrmCustomerDO.class);
        customerDO.setOwnerUserId(SecurityFrameworkUtils.getLoginUserId());
        customerDO.setNextTime(LocalDateTime.now());
        customerDO.setCollectTime(LocalDateTime.now());
        customerMapper.insert(customerDO);

        //更新线索
        crmCluesDO.setStatus(CluesStatusEnum.STATUS_1.getValue());
        crmCluesDO.setCustomerId(customerDO.getId());
        cluesMapper.updateById(crmCluesDO);

        //是否更新跟踪记录
        if(ShopCommonEnum.ENABLE_1.getValue().equals(createReqVO.getIsTransfer())){
            crmRecordMapper.update(CrmRecordDO.builder()
                    .types(TypesEnum.CUSTOMER.getValue())
                    .typesId(customerDO.getId()).build(),
                    new LambdaQueryWrapper<CrmRecordDO>().eq(CrmRecordDO::getTypesId,crmCluesDO.getId()));
        }
    }


    @Override
    public CustomerImportRespVO importList(List<CrmCluesImportVO> importUsers, String deptId, String adminIds,
                                           Integer averageType) {
        CustomerImportRespVO respVO = CustomerImportRespVO.builder().createNames(new ArrayList<>())
                .failureNames(new LinkedHashMap<>()).build();
        //处理客户归属方案
        //如果只选择了机构没有选择用户直接获取当前部门下的用户
        List<Long> userList = null;
        if(StrUtil.isNotEmpty(deptId) && StrUtil.isEmpty(adminIds)){
            Set<Long> deptIds = adminUserService.getDeptCondition(Long.valueOf(deptId));
            List<AdminUserDO> adminUserDOS =  userMapper.selectList(new LambdaQueryWrapperX<AdminUserDO>()
                    .in(AdminUserDO::getDeptId,deptIds));
            userList = adminUserDOS.stream().map(AdminUserDO::getId).collect(Collectors.toList());
            if(userList.isEmpty()){
                throw exception(new ErrorCode(202409110,"当前部门下没有用户，清重新选择"));
            }
        }else{
            userList = StrUtil.split(adminIds,",").stream().map(Long::parseLong).toList();
        }


        int i = 1;
        int j = 0;
        int adminCount = userList.size();
        for (CrmCluesImportVO importVO : importUsers){
            if(StrUtil.isEmpty(importVO.getName())){
                respVO.getFailureNames().put("第" + i + "行:", "线索名称为空，已经被过滤掉");
                continue;
            }
            Long count = cluesMapper.selectCount(new LambdaQueryWrapper<CrmCluesDO>()
                    .eq(CrmCluesDO::getName,importVO.getName()));
            if(count > 0){
                respVO.getFailureNames().put("第" + i + "行:", "线索名称已经存在，已经被过滤掉");
                continue;
            }
            CrmCluesDO crmCluesDO = BeanUtils.toBean(importVO, CrmCluesDO.class);
            Long adminId = 0L;
            if(ShopCommonEnum.AVG_1.getValue().equals(averageType)){
                //平均分配
                adminId = userList.get(j);
                if(j == (adminCount - 1)){
                    j = 0;
                }else{
                    j++;
                }
            }else{
                //随机分配
                Random random = new Random();
                int num = random.nextInt(adminCount);
                adminId = userList.get(num);
            }
            crmCluesDO.setOwnerUserId(adminId);
            cluesMapper.insert(crmCluesDO);
            respVO.getCreateNames().add("第" + i + "行:导入成功用户名->" + importVO.getName());
            i++;
        }
        return respVO;
    }




    @Override
    public void transfer(CrmCluesTransferVO transferVO) {
        //客户
        List<CrmCluesDO> crmCluesDOS = cluesMapper.selectList(new LambdaQueryWrapper<CrmCluesDO>().
                in(CrmCluesDO::getId,transferVO.getCluesIds()));
        if(crmCluesDOS == null || crmCluesDOS.isEmpty()){
            throw exception(new ErrorCode(202409111,"线索信息不存在"));
        }

        int adminCount = transferVO.getOwnerAdminIds().size();
        int i = 0;
        for (CrmCluesDO crmCluesDO : crmCluesDOS){
            Long adminId;
            if(ShopCommonEnum.AVG_1.getValue().equals(transferVO.getAverageType())){
                //平均分配
                adminId = transferVO.getOwnerAdminIds().get(i);
                if(i == (adminCount - 1)){
                    i = 0;
                }else{
                    i++;
                }
            }else{
                //随机分配
                Random random = new Random();
                int num = random.nextInt(adminCount);
                adminId = transferVO.getOwnerAdminIds().get(num);
            }
            crmCluesDO.setOwnerUserId(adminId);
            crmCluesDO.setCollectTime(LocalDateTime.now());

            cluesMapper.updateById(crmCluesDO);
        }
    }

}